'''
Created on Apr 25, 2012


@author: Dan Baskette
@Date:    5/9/2012
@Input:    Nodes:  Array of Nodes in Cluster
           Users:  Array of valid Users in Cluster
@Output:   Nodes:  Updates the Nodes Objects in the Nodes Array
@Check:    0 -  Data was gathered from All Nodes
           1 -  Data Gathering was Unsuccessful

'''


from Base import Base
import Queue
import threading
import re

class NodeCheck(Base):
    
    Nodes = []
    Log = []
    Roles = []
    Users = []
    returnQueue = Queue.Queue()
    

      
    def __RamCheck(self):
        
        """
        This method looks up the available RAM on each server in the
        cluster and sets the value on each Node Object in the
        Array of Nodes
        """
        ramCMD = str(self.installSudo) + "cat /proc/meminfo"
        threadCount = 0
        Threads = [] 
        for node in self.Nodes:
            Threads.append(threading.Thread(target=self.SSHExec, args=(ramCMD, node.hostName, self.installUser, self.installPW)))
            Threads[threadCount].daemon = True
            Threads[threadCount].start()     
            threadCount = threadCount + 1
        for thread in Threads:
            thread.join()
            (hostName, username, status, results) = self.returnQueue.get()
            ramValue = long((str(results[0]).split(":")[1][:-3]).strip()) / 1024
            if (status == 0):
                for node in self.Nodes:
                    if (node.hostName == hostName):
                        node.ramInfo = ramValue
    
    def __CpuCheck(self):
        
        """
        This method looks up the CPU Information on each server in the
        cluster and sets the value on each Node Object in the
        Array of Nodes
        """
             
        
        cpuCMD = str(self.installSudo) + "cat /proc/cpuinfo | egrep \"processor|model name\""
        threadCount = 0
        Threads = [] 
        for node in self.Nodes:
            Threads.append(threading.Thread(target=self.SSHExec, args=(cpuCMD, node.hostName, self.installUser, self.installPW)))
            Threads[threadCount].daemon = True
            Threads[threadCount].start()     
            threadCount = threadCount + 1
        for thread in Threads:
            thread.join()
            (hostName, username, status, results) = self.returnQueue.get()
            cpuCount = str(results).count("processor")
            cpuType = (str(results[1]).split(":")[1]).strip()
            if (status == 0):
                for node in self.Nodes:
                    if (node.hostName == hostName):
                        node.cpuCount = cpuCount
                        node.cpuType = cpuType             
    
    def __RawCapacity(self):
        
        """
        This method looks up the raw Capacity of the drives on each server
        in the cluster and sets the value on each Node Object in the
        Array of Nodes.  It depends on the disks being defined in the
        object prior to this method.
        """
     
     
        threadCount = 0
        Threads = [] 
            
        for node in self.Nodes:
            for disk in node.Disks:
                diskName = re.sub("\d+","",str(disk.deviceName)[5:])
                capCMD = str(self.installSudo) + "cat /proc/partitions | grep " + diskName
                self.LogInfo(capCMD)
                Threads.append(threading.Thread(target=self.SSHExec, args=(capCMD, node.hostName, self.installUser, self.installPW)))
                Threads[threadCount].daemon = True
                Threads[threadCount].start()     
                threadCount = threadCount + 1
        for thread in Threads:
            thread.join()
            (hostName, username, status, results) = self.returnQueue.get()

            if (status==0):
                capacity = str(results).split()[3]
                device = str(results).split()[4][:-4]
                for node in self.Nodes:
                        if (node.hostName == hostName):
                            for disk in node.Disks:
                                if (device in disk.deviceName):
                                    disk.rawCapacity = long(capacity) / 1024 / 1024
            else:
                disk.rawCapacity = 0    
                                          
    def __OSVersion(self):
        
        """
       
        """
     
     
        threadCount = 0
        Threads = [] 
            
        for node in self.Nodes:
            releaseCMD = str(self.installSudo) + "cat /etc/redhat-release"
            Threads.append(threading.Thread(target=self.SSHExec, args=(releaseCMD, node.hostName, self.installUser, self.installPW)))
            Threads[threadCount].daemon = True
            Threads[threadCount].start()     
            threadCount = threadCount + 1
        for thread in Threads:
            thread.join()
            (hostName, username, status, results) = self.returnQueue.get()
            release = str(results).split('release')[1][:-4]
            if (status == 0):
                for node in self.Nodes:
                    if (node.hostName == hostName):
                        node.osVersion = release                   
                                
                                
                                
                                
                                
    def __CalcTotalRawCapacity(self):
        
        """
        Calculate Total Capacity of all drives on a given Node
        """
        
        for node in self.Nodes:
            raw_Capacity = 0 
            node.total_rawCapacity = 0
            for disk in node.Disks:
                node.total_rawCapacity += disk.rawCapacity
        
    
        
    def Inventory(self):
        
        """
        Build Inventory of Hardware in Cluster
        
        - This is the main entry point to the Module.  It will call all
          the internal methods 
        """
        
        self.__RamCheck()
        self.__CpuCheck()
        self.__RawCapacity()
        self.__CalcTotalRawCapacity()
        self.__OSVersion()
        
        # Log the Inventory to Info Log
        
        self.LogInfo("****  Node Inventory ****")
        print "    * Gathering Node Inventory (See Logs for Details)"
        for node in self.Nodes:
            self.LogInfo("-----------------------------------------")
            self.LogInfo(str(node.hostName) + "    " + str(node.ipAddress))
            self.LogInfo("CPUs Qty: " + str(node.cpuCount) + "  CPU Type: " + str(node.cpuType))
            self.LogInfo("RAM: " + str(node.ramInfo))
            self.LogInfo("JVM: " + str(node.javaVersion))
            self.LogInfo("OS:  " + str(node.osVersion))
            self.LogInfo("Disks: ",)
            for disk in node.Disks:
                self.LogInfo("  +  " + str(disk.deviceName) + "    " + str(disk.rawCapacity) + " GB")
            
    def ConnectivityCheck(self):
        
        ''' 
        SSH test:   SSH To all Nodes
        '''
        sshTestStatus = 0
        threadCount = 0
        Threads = []
        for node in self.Nodes:
            self.LogInfo("Attempting SSH To " + str(node.hostName))
            sshtestCMD = "hostname"
            Threads.append(threading.Thread(target=self.SSHExec, args=(sshtestCMD, node.hostName, self.installUser, self.installPW)))
            Threads[threadCount].daemon = True
            Threads[threadCount].start()
            threadCount = threadCount + 1
        for thread in Threads:
            thread.join()
            (hostName, username, status, results) = self.returnQueue.get()
            if (status == 0):
                self.LogInfo("SSH To " + str(hostName) + " Successful")
                print "        * SSH To " + str(hostName) + " Successful"
            else:
                print "        * SSH To " + str(hostName) + " Failed"
                self.LogInfo("SSH To " + str(hostName) + " Failed")
                sshTestStatus = -1
        if (sshTestStatus == 0):
            self.LogInfo("SSH Connectivity Tests Successful")
        else:
            self.LogError("SSH Connectivity Tests Failed")

        return sshTestStatus
            
            
            

    def __init__(self, Nodes, Users):
        Base.__init__(self)
        self.Users = Users
        self.Nodes = Nodes
        Base.SetUsers(self, Users)
       
